home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse1 / dtdelt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  23.9 KB  |  800 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DTD PROCESSOR                                      */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    DTDELT.C                                           */
  51. /*   AUTHOR:         Jim Heath                                          */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include <stdio.h>
  60. #include <setjmp.h>
  61. #include <string.h>
  62. #include <ctype.h>
  63. #include "qntyset.h"
  64. #include "dtd.h"
  65. #include "dtdfncs.h"
  66. #include "dtdglbl.h"
  67.  
  68. extern int debug;
  69. char *rec;
  70.  
  71. static char savebuff[1024], *savebuffptr = savebuff;
  72. static int saveinfo = OFF, savebufflen = 0, miscflag = 0;
  73. static int eltindex = 0;
  74. static char eltnames[MAXELTS * (NAMELEN + 1)];
  75.  
  76. /* ============================================================ */
  77. /* We have just finished reading <!ELEMENT from the input stream
  78. */
  79. int doelement()
  80. {
  81.  
  82.    FUNCTRACE("doelt1");
  83.    /*   memset(eltnames, '\0', sizeof(eltnames));
  84.    eltindex = 0;*/
  85.    saveinfo = OFF;
  86.    if (INPPS() == EOF)
  87.       terminate(1, "EOF in ELEMENT declaration");
  88.    ADDCHAR(SPACE);
  89.    if (dosingleelt())
  90.       return(1);
  91.    return(doeltgroup());
  92. }
  93. /* ============================================================ */
  94. int dosingleelt()
  95. {
  96.    char namearray[NAMELEN + 1], temp[128], *mydecl;
  97.    char rankstem[NAMELEN + 1], *stemptr = rankstem;
  98.    int j;
  99.  
  100.    if (geteltname(namearray) == GOOD) {
  101.       ADDSTRING(namearray);
  102.       if ((j = INPPS()) == EOF)
  103.          terminate(1, "EOF in element declaration");
  104.       j = jgetc();
  105.       if (ISDIGIT(j)) {
  106.          jungetc(j);
  107.          ADDCHAR(SPACE);
  108.          if ((j = INPNBR(&stemptr, NAMELEN - 1, noxlat)) == EOF)
  109.             terminate(1, "EOF in element declaration");
  110.          ADDSTRING(rankstem);
  111.          if (j != GOOD)
  112.             syntxerr("syntax error in rank suffix");
  113.          if ((strlen(namearray) + strlen(rankstem)) > NAMELEN)
  114.             syntxerr("combined rank stem + rank suffix > NAMELEN");
  115.          strcat(namearray, rankstem);
  116.       }
  117.       else jungetc(j);
  118.  
  119.       if (eltindex >= MAXELTS)
  120.          terminate(1, "MAX # of elements has been exceeded");
  121.       if (ckfordup(eltindex++, eltnames, namearray) == TRUE){
  122.          GETDECLADDR(&mydecl);
  123.          printf("%s\n", mydecl);
  124.          strcpy(temp, "Multiple element declarations exist for:  ");
  125.          strcat(temp, namearray);
  126.          terminate(1, temp);
  127.       }
  128.       putsymtbl(namearray);
  129.       doelt2(namearray, 1);
  130.       return(TRUE);
  131.    }
  132.    return(FALSE);
  133. }
  134. /* ============================================================ */
  135. doeltgroup()
  136. {
  137.    int eltcount;
  138.    REGISTER int namecount, j;
  139.    char *mydecl, temp[128], rankstem[NAMELEN + 1], *stemptr = rankstem;
  140.    char tempnames[GRPCNT * (NAMELEN + 1)];
  141.  
  142.    eltcount = namecount = getnamegrp(tempnames, ISALPHA, isnmchar);
  143.    memset(rankstem, '\0', sizeof(rankstem));
  144.    if ((j = INPPS()) == EOF)
  145.       terminate(1, "EOF in element declaration");
  146.    j = jgetc();
  147.    if (ISDIGIT(j)) {
  148.       jungetc(j);
  149.       ADDCHAR(SPACE);
  150.       if ((j = INPNBR(&stemptr, NAMELEN - 1, noxlat)) == EOF)
  151.          terminate(1, "EOF in element declaration");
  152.       ADDSTRING(rankstem);
  153.       if (j != GOOD)
  154.          syntxerr("syntax error in rank suffix");
  155.    }
  156.    else jungetc(j);
  157.  
  158.    if (eltindex >= MAXELTS)
  159.       terminate(1, "MAX # of elements has been exceeded");
  160.    if ((strlen(tempnames) + strlen(rankstem)) > NAMELEN)
  161.       syntxerr("combined rank stem + rank suffix > NAMELEN");
  162.    strcat(tempnames, rankstem);
  163.  
  164.    if (ckfordup(eltindex++, eltnames, tempnames) == FALSE)
  165.       putsymtbl(tempnames);
  166.    else {
  167.       GETDECLADDR(&mydecl);
  168.       printf("%s\n", mydecl);
  169.       strcpy(temp, "Multiple element declarations exist for:  ");
  170.       strcat(temp, tempnames);
  171.       terminate(1, temp);
  172.    }
  173.    doeltgroup2(namecount, eltcount, tempnames, rankstem, mydecl);
  174.    return(eltcount);
  175. }
  176. /* ============================================================ */
  177. doeltgroup2(namecount, eltcount, tempnames, rankstem, mydecl)
  178. int namecount, eltcount;
  179. char tempnames[], rankstem[], *mydecl;
  180. {
  181.    char temp[128], *nmptr = tempnames;
  182.  
  183.    memset(savebuff, '\0', sizeof(savebuff));
  184.    savebuffptr = savebuff;
  185.    savebufflen = 0;
  186.    saveinfo = ON;
  187.    doelt2(tempnames, eltcount);
  188.    nmptr += (NAMELEN + 1);
  189.    namecount--;
  190.    while(namecount--){
  191.       if (eltindex >= MAXELTS)
  192.          terminate(1, "MAX # of elements has been exceeded");
  193.       if ((strlen(nmptr) + strlen(rankstem)) > NAMELEN)
  194.          syntxerr("combined rank stem + rank suffix > NAMELEN");
  195.       strcat(nmptr, rankstem);
  196.       if (ckfordup(eltindex++, eltnames, nmptr) == FALSE)
  197.          putsymtbl(nmptr);
  198.       else {
  199.          GETDECLADDR(&mydecl);
  200.          printf("%s\n", mydecl);
  201.          strcpy(temp, "Multiple element declarations exist for:  ");
  202.          strcat(temp, nmptr);
  203.          terminate(1, temp);
  204.       }
  205.       safewrite(symbfile, &miscflag, sizeof(miscflag));
  206.       nmptr += (NAMELEN + 1);
  207.       safewrite(treefile, savebuff, savebufflen);
  208.    }
  209.    return(eltcount);
  210. }
  211. /* ============================================================ */
  212. /* ============================================================ */
  213. void doelt2(tempnames, tempcount)
  214. char *tempnames;
  215. int tempcount;
  216. {
  217.    extern int symbfile;
  218.    REGISTER int j;
  219.  
  220.    dominimization();
  221.    docontent(tempnames);
  222.    safewrite(symbfile, (char *) &miscflag, sizeof(miscflag));
  223.    if (INPPS() == EOF)
  224.       terminate(1, "EOF in ELEMENT declaration");
  225.    if ((j = jgetc()) == '-'){
  226.       ADDSTRING(" -");
  227.       doexclusions(tempnames, tempcount);
  228.    }
  229.    else
  230.       jungetc(j);
  231.    if (INPPS() == EOF)
  232.       terminate(1, "EOF in ELEMENT declaration");
  233.    if ((j = jgetc()) == '+'){
  234.       ADDSTRING(" +");
  235.       doinclusions(tempnames, tempcount);
  236.    }
  237.    else
  238.       jungetc(j);
  239.    if (INPPS() == EOF)
  240.       terminate(1, "EOF in ELEMENT declaration");
  241.    if ((j = jgetc()) == MDC) {
  242.       ADDCHAR(MDC);
  243.       return;
  244.    }
  245.    ADDCHAR(j);
  246.    syntxerr("Expected MDC at this point");
  247. }
  248. /* =========================================================== */
  249. dominimization()
  250. {
  251.    int j, pscount;
  252.  
  253.    miscflag = 0;
  254.    if ((pscount = INPPS()) == EOF)
  255.       terminate(1, "EOF in ELEMENT declaration");
  256.    ADDCHAR(SPACE);
  257.    if ((j = TOUPPER(jgetc())) == EOF)
  258.       terminate(1, "EOF in ELEMENT declaration");
  259.    if ((j != 'O') && (j != '-'))
  260.       syntxerr("minimization must be specified");
  261.    ADDCHAR(j);
  262.    if (j == 'O')
  263.       miscflag |= 1;
  264.    if ((pscount = INPPS()) == EOF)
  265.       terminate(1, "EOF in ELEMENT declaration");
  266.    if (pscount <= 0)
  267.       syntxerr("Expected PS+ at this point");
  268.    ADDCHAR(SPACE);
  269.    if ((j = TOUPPER(jgetc())) == EOF)
  270.       terminate(1, "EOF in ELEMENT declaration");
  271.    if ((j != 'O') && (j != '-')) {
  272.       ADDCHAR(j);
  273.       syntxerr("error in minimization");
  274.    }
  275.    if (j == 'O')
  276.       miscflag |= 2;
  277.    ADDCHAR(j);
  278.    if ((pscount = INPPS()) == EOF)
  279.       terminate(1, "EOF in ELEMENT declaration");
  280.    ADDCHAR(SPACE);
  281. }
  282. /* =========================================================== */
  283. int geteltname(ptr)
  284. char *ptr;
  285. {
  286.    int j;
  287.    char temp[NAMELEN+1], *tmpptr = temp;
  288.    tmpptr = temp;
  289.  
  290.    if ((j = INPNAME(&tmpptr, NAMELEN, TOUPPER)) == EOF)
  291.       terminate(1, "EOF in ELEMENT declaration");
  292.    if (j >= GOOD) {
  293.       strcpy(ptr, temp);
  294.       return (GOOD);
  295.    }
  296.    return(BAD);
  297. }
  298. /* =========================================================== */
  299. void docontent(tempeltname)
  300. char *tempeltname;
  301. {
  302.    char tempname[NAMELEN + 1];
  303.    extern int symbfile;
  304.    char namearray[NAMELEN + 1], *tmpptr = namearray;
  305.    REGISTER int j;
  306.    char *src, *dest;
  307.  
  308.    memset(tempname, '\0', sizeof(tempname));
  309.    strncpy(tempname, tempeltname, NAMELEN);
  310.    /* writename(name, 'x', NO);*/
  311.    if ((j = INPNAME(&tmpptr, NAMELEN, TOUPPER)) == EOF)
  312.       terminate(1, "EOF in ELEMENT declaration");
  313.    switch(j) {
  314.    case KW_RCDATA:
  315.       miscflag &= (~1);
  316.       ADDSTRING("RCDATA");
  317.       writename("rCDATA", '*');
  318.       break;
  319.    case KW_CDATA:
  320.       miscflag &= (~1);
  321.       ADDSTRING("CDATA");
  322.       writename("cDATA", '*');
  323.       break;
  324.    case KW_ANY:
  325.       miscflag &= (~1);
  326.       ADDSTRING("ANY");
  327.       writename("aNY", '*');
  328.       break;
  329.    case KW_EMPTY:
  330.       miscflag &= (~1);
  331.       ADDSTRING("EMPTY");
  332.       miscflag = 2 | (1 << 7);
  333.       writename("eMPTY", '1');
  334.       break;
  335.    default:
  336.       if (j >= GOOD)
  337.          syntxerr("Syntax error while processing content model");
  338.       rec = getagroup(1);
  339.       if (countnames(rec) > GRPGTCNT )
  340.          syntxerr("Name count exceed GRPGTCNT");
  341.       if (nestlevel(rec) > GRPLVL)
  342.          syntxerr("Nesting level exceeds GRPLVL");
  343.       getsubexprs(0, strlen(rec) - 1, FALSE, NONE, NONE, NONE, FALSE);
  344.       for (src = dest = rec; *src != '\0';){
  345.          if (*src != EE)
  346.             *dest++ = *src++;
  347.          else
  348.             src++;
  349.       }
  350.       *dest = '\0';
  351.       writecmodel(tempname);
  352.       writecmodel(rec);
  353.    }
  354. }
  355. /* =========================================================== */
  356. /* =========================================================== */
  357. void getsubexprs(low, high, foundconnector, connector, group_oi, curcon, rqflg)
  358. int low, high, foundconnector, connector, group_oi, curcon, rqflg;
  359. {
  360.    int nestlvl, temp, tempoi, reqflg;
  361.    REGISTER int current, oi;
  362.    static int first_elt_is_opt = FALSE;
  363.  
  364.    FUNCTRACE("getsubexprs");
  365.    if (debug & CMTRC) {
  366.       printf("Enter getsubexprs with:  ");
  367.       for (temp = low; temp <= high; temp++)
  368.          putchar(rec[temp]);
  369.       printf(" foundconnector = %d\n", foundconnector);
  370.    }
  371.  
  372.    oi = simplify(rec, &low, &high, &foundconnector, &connector);
  373.    if (rqflg == TRUE)
  374.       first_elt_is_opt = TRUE;
  375.    if ((oi == '*') || (oi == '?'))
  376.       first_elt_is_opt = TRUE;
  377.    current = nestlvl = 0;
  378.  
  379.    nestlvl = 0;
  380.    for(current = low; current <= high; current++) {
  381.       if (rec[current] == GRPO)
  382.          nestlvl++;
  383.       else if (rec[current] == GRPC)
  384.          nestlvl--;
  385.       else if (isconnector(rec[current])) {
  386.          if (nestlvl == 0) {
  387.             chkconnector(rec, current, high);
  388.             if (connector != '&')
  389.                writeconnector(rec[current], oi);
  390.             if ((connector != '&') && (rec[current] == '&')) {
  391.                writecount(andcount(rec, current + 1, high));
  392.                connector = '&';
  393.             }
  394.             if ((rec[current] == '|') || (rec[current] == '&'))
  395.                reqflg = TRUE;
  396.             else
  397.                reqflg = FALSE;
  398.             getsubexprs(low, current - 1, TRUE, NONE, oi, rec[current], reqflg);
  399.             getsubexprs(current + 1, high, FALSE, connector, '1', rec[current], reqflg);
  400.             return;
  401.          }
  402.          else continue;
  403.       }
  404.       else if (isnamerni(&rec[current], NAMELEN)) {
  405.          char *cname;
  406.          int len;
  407.          cname = getnamerni(&rec[current]);
  408.          len = strlen(cname);
  409.          if (*cname == RNI){
  410.             if (strcmp(cname, "#PCDATA") != 0)
  411.                syntxerr("illegal value in content model!");
  412.             else if (isoi(rec[current + len]))
  413.                syntxerr("cannot have occurrence indicator on #PCDATA");
  414.          }
  415.          if (foundconnector) {
  416.             tempoi = updateoi(oi, rec[current + len]);
  417.             writename(cname, tempoi);
  418.             first_elt_is_opt = FALSE;
  419.             return;
  420.          }
  421.          else if (( current + len) >= high) {
  422.             tempoi = updateoi(oi, rec[current + len]);
  423.             writename(cname, tempoi);
  424.             first_elt_is_opt = FALSE;
  425.             return;
  426.          }
  427.       }
  428.    }
  429. }
  430.  
  431. /* =========================================================== */
  432. /* This function takes expressions like (((X,Y),Z*)+)*
  433.    and simplifies them down to ((X,Y),Z*)*, i.e., it removes 
  434.       excess parentheses at the outermost level and combines
  435.       occurrence indicators.  It returns the OI of the group.
  436.                   */
  437. simplify(temprec, low, high, foundconnector, connector)
  438. char temprec[];
  439. int *low, *high, *foundconnector, *connector;
  440. {
  441.    REGISTER int nestlvl, temp;
  442.    int oi = '1';
  443.  
  444.    FUNCTRACE("simplify");
  445.    if (debug & SIMPTRC) {
  446.       printf("ENTER SIMPLIFY:  ");
  447.       for (temp = *low; temp <= *high; temp++)
  448.          putchar(temprec[temp]);
  449.       printf(" foundconnector = %d\n", *foundconnector);
  450.       printf(" connector = %d\n", *connector);
  451.    }
  452. SIMPLIFY:
  453.    /* if this group is not bounded by GRPO, GRPC, just return
  454.       the default occurrence indicator */
  455.    if (temprec[*low] != GRPO)
  456.       return(oi);
  457.    if ((temprec[*high] != GRPC) && (temprec[(*high) - 1] != GRPC))
  458.       return(oi);
  459.    /* scan through to see if entire group is bounded by GRPO, GRPC */
  460.    nestlvl = 0;
  461.    for (temp = *low; temp <= *high; temp++) {
  462.       if (temprec[temp] == GRPO)
  463.          nestlvl++;
  464.       else if (temprec[temp] == GRPC)
  465.          nestlvl--;
  466.  
  467.       if (nestlvl == 0) {
  468.          *foundconnector = FALSE;
  469.          /* we balanced parentheses before the end of the group! */
  470.          if (temp < ((*high) - 1))
  471.             return(oi);
  472.          break;
  473.       }
  474.    }
  475.  
  476.    /* the whole buffer is bounded by GRPO, GRPC */
  477.    /* indicate we have not yet found a connector */
  478.    *connector = NONE;
  479.  
  480.    /* if we are on the last byte of the message then we are on a ')'
  481.       and there is no OI to worry about */
  482.    if (temp == *high)
  483.       (*high)--;
  484.       /* else, we are just before the OI for the group */
  485.    else {
  486.       oi = updateoi(oi, temprec[*high]);
  487.       (*high) -= 2;
  488.    }
  489.    /* bump past the first GRPO */
  490.    (*low)++;
  491.    if (debug & SIMPTRC) {
  492.       printf("AFTER SIMPLIFICATION:  ");
  493.       for (temp = *low; temp <= *high; temp++)
  494.          putchar(temprec[temp]);
  495.       printf(" foundconnector = %d\n", *foundconnector);
  496.       printf(" connector = %d\n", *connector);
  497.    }
  498.    goto SIMPLIFY;
  499. }
  500. /* =========================================================== */
  501. int updateoi(oldoi, newoi)
  502. REGISTER int oldoi;
  503. REGISTER char newoi;
  504. {
  505.    FUNCTRACE("updateoi");
  506.    if ((newoi != '+') && (newoi != '*') && (newoi != '?'))
  507.       return(oldoi);
  508.    if (oldoi == '*')
  509.       return('*');
  510.    if (newoi == '*')
  511.       return('*');
  512.    if (newoi == '+')
  513.       if ((oldoi == '+') || (oldoi == '1'))
  514.          return('+');
  515.    if (newoi == '?')
  516.       if ((oldoi == '?') || (oldoi == '1'))
  517.          return('?');
  518.    return('*');
  519. }
  520. /* =========================================================== */
  521. static void writeconnector(cnnctr, oi)
  522. char cnnctr, oi;
  523. {
  524.    extern int treefile;
  525.    TREEREC trec;
  526.    REGISTER int j;
  527.    REGISTER char *src;
  528.  
  529.    FUNCTRACE("writeconnector");
  530.    memset((char *)&trec, '\0', sizeof(trec));
  531.    /*printf("connector node = %c  (oi = %c)\n", cnnctr, oi);*/
  532.    trec.Tinfo[0] = cnnctr;
  533.    trec.Toi = oi;
  534.    safewrite(treefile, (char *)&trec, sizeof(trec));
  535.    if (saveinfo == ON) {
  536.       for(j = 0, src = (char *)&trec; j < sizeof(trec); j++)
  537.          *savebuffptr++ = *src++;
  538.       savebufflen += sizeof(trec);
  539.    }
  540. }
  541. /* =========================================================== */
  542. void writecount(count)
  543. int count;
  544. {
  545.    extern int treefile;
  546.    REGISTER int j;
  547.    REGISTER char *src;
  548.  
  549.    FUNCTRACE("writecount");
  550.    safewrite(treefile, (char *)&count, sizeof(count));
  551.    if (saveinfo == ON) {
  552.       for(j = 0, src = (char *)&count; j < sizeof(count); j++)
  553.          *savebuffptr++ = *src++;
  554.       savebufflen += sizeof(count);
  555.    }
  556. }
  557.  
  558. /* =========================================================== */
  559. static void writename(nodename, oi)
  560. char *nodename;
  561. char oi;
  562. {
  563.    REGISTER char *src;
  564.    extern int treefile;
  565.    TREEREC trec;
  566.    REGISTER int j;
  567.    int len;
  568.  
  569.    FUNCTRACE("writename");
  570.    memset((char *)&trec, '\0', sizeof(trec));
  571.    len = strlen(nodename);
  572.    if (strcmp(nodename, "#PCDATA") == 0)
  573.       oi = '*';
  574.    for(j = 0; j < len; j++)
  575.       trec.Tinfo[j] = *nodename++;
  576.    trec.Toi = oi;
  577.    trec.Tcontreq = 0x7777;
  578.    safewrite(treefile, (char *)&trec, sizeof(trec));
  579.    if (saveinfo == ON) {
  580.       for(j = 0, src = (char *)&trec; j < sizeof(trec); j++)
  581.          *savebuffptr++ = *src++;
  582.       savebufflen += sizeof(trec);
  583.    }
  584. }
  585.  
  586. /* ============================================================ */
  587. void putsymtbl(name)
  588. char *name;
  589. {
  590.    SYMBREC symbrec;
  591.  
  592.    extern int symbfile;
  593.    REGISTER int j;
  594.  
  595.    FUNCTRACE("putsymbtbl");
  596.    if (strcmp(name, rootelt) == 0) {
  597.       for (j = 0; rootelt[j] != '\0'; j++)
  598.          rootelt[j] = '\0';
  599.       *name |= (1 << 7);
  600.    }
  601.    memset((char *)&symbrec, '\0', sizeof(SYMBREC));
  602.    symbrec.Smin = 0;
  603.    /*printf("symbol = %s\n", name);*/
  604.    for (j = 0; (j < sizeof(symbrec.Sname)) && (name[j] != '\0'); j++)
  605.       symbrec.Sname[j] = name[j];
  606.    safewrite(symbfile, (char *)&symbrec, sizeof(symbrec));
  607. }
  608. /* ============================================================ */
  609. andcount(buff, low, high)
  610. char buff[];
  611. int low;
  612. REGISTER int high;
  613. {
  614.    REGISTER int j;
  615.    int nestlvl, count;
  616.  
  617.    nestlvl = count = 0;
  618.    FUNCTRACE("andcount");
  619.    for (j = low; j <= high; j++){
  620.       if (buff[j] == '&') {
  621.          if (nestlvl == 0)
  622.             count++;
  623.       }
  624.       else if (buff[j] == '(')
  625.          nestlvl++;
  626.       else if (buff[j] == ')')
  627.          nestlvl--;
  628.    }
  629.    return(count + 2);
  630. }
  631. /* ============================================================ */
  632. void chkconnector(buf, strt, end)
  633. char buf[];
  634. REGISTER int strt, end;
  635. {
  636.    int nestlvl = 0;
  637.    char connector = buf[strt++];
  638.  
  639.    FUNCTRACE("chkconnector");
  640.    while(strt != end) {
  641.       if (isconnector(buf[strt]) && (nestlvl == 0)) {
  642.          if (buf[strt] != connector)
  643.             syntxerr("different connectors");
  644.       }
  645.       else if (buf[strt] == '(')
  646.          nestlvl++;
  647.       else if (buf[strt] == ')')
  648.          nestlvl--;
  649.       strt++;
  650.    }
  651. }
  652. /* ============================================================ */
  653. /* ============================================================ */
  654. int ckfordup(index, existingnames, name)
  655. REGISTER int index;
  656. char *existingnames, *name;
  657. {
  658.    REGISTER int j;
  659.    for (j = 0; j <index; j++, existingnames += (NAMELEN + 1)) {
  660.       if (strcmp(existingnames, name) == 0)
  661.          return(TRUE);
  662.    }
  663.    strcpy(existingnames, name);
  664.    return(FALSE);
  665. }
  666. /* ============================================================ */
  667. static void doinclusions(names, count)
  668. REGISTER char *names;
  669. int count;
  670. {
  671.    int j, k, i, flag;
  672.    REGISTER int kk;
  673.    char *temp;
  674.    char tempnames[GRPCNT * (NAMELEN + 1)];
  675.  
  676.    j = getnamegrp(tempnames, ISALPHA, isnmchar);
  677.    for (k = 0; k < count; k++, names += (NAMELEN + 1)) {
  678.       *names &= 0x7f;
  679.       for (kk = 0, flag = OFF; kk < (NAMELEN + 1); kk++) {
  680.          if (*(names + kk) == '\0')
  681.             flag = ON;
  682.          if (flag == ON)
  683.             *(names + kk) = '\0';
  684.       }
  685.       safewrite(inclfile, names, (NAMELEN + 1));
  686.       safewrite(inclfile, (char *) &j, sizeof (j));
  687.       for (temp = tempnames, i = 0; i < j; i++, temp += (NAMELEN + 1))
  688.          safewrite(inclfile, temp, (NAMELEN + 1));
  689.    }
  690. }
  691. /* ============================================================ */
  692. static void doexclusions(names, count)
  693. char *names;
  694. int count;
  695. {
  696.    int j, k, i, kk, flag;
  697.    char *temp;
  698.    char tempnames[GRPCNT * (NAMELEN + 1)];
  699.  
  700.    j = getnamegrp(tempnames, ISALPHA, isnmchar);
  701.    for (k = 0; k < count; k++, names += (NAMELEN + 1)) {
  702.       *names &= 0x7f;
  703.       for (kk = 0, flag = OFF; kk < (NAMELEN + 1); kk++) {
  704.          if (*(names + kk) == '\0')
  705.             flag = ON;
  706.          if (flag == ON)
  707.             *(names + kk) = '\0';
  708.       }
  709.       safewrite(exclfile, names, (NAMELEN + 1));
  710.       safewrite(exclfile, (char *) &j, sizeof (j));
  711.       for (temp = tempnames, i = 0; i < j; i++, temp += (NAMELEN + 1))
  712.          safewrite(exclfile, temp, (NAMELEN + 1));
  713.    }
  714. }
  715. /* ============================================================ */
  716.  
  717. /* ============================================================ */
  718. int countnames(mdlptr)
  719. char *mdlptr;
  720. {
  721. #define FIRSTCHAR(x) ((isascii(x)) && (isalpha(x)) || (x == RNI))
  722. #define OTHERCHAR(x) ((FIRSTCHAR(x)) || (isdigit(x)) || (x == '-') || (x == '.'))
  723.    int count = 0;
  724.    while(1) {
  725.       while (FIRSTCHAR(*mdlptr) == FALSE) {
  726.          if(*mdlptr == '\0')
  727.             return(count);
  728.          if (*mdlptr == GRPO)
  729.             count++;
  730.          mdlptr++;
  731.       }
  732.       mdlptr++;
  733.       while (OTHERCHAR(*mdlptr))
  734.          mdlptr++;
  735.       count++;
  736.    }
  737. }
  738. /* ============================================================ */
  739. /* ============================================================ */
  740. int nestlevel(mdl)
  741. char *mdl;
  742. {
  743.    int maxlvl = 0, currlevel = 0;
  744.  
  745.    while(*mdl != 0) {
  746.       if (*mdl == GRPO) {
  747.          currlevel++;
  748.          if (currlevel > maxlvl)
  749.             maxlvl = currlevel;
  750.       }
  751.       else if (*mdl == GRPC)
  752.          currlevel--;
  753.       mdl++;
  754.    }
  755.    return(maxlvl);
  756. }
  757. /* ============================================================ */
  758. void writecmodel(rec)
  759. char *rec;
  760. {
  761.    char *strstr();
  762.    char buff[1000], *cptr, *dest = buff;
  763.    char *pcdata = "#PCDATA", *src;
  764.  
  765.    memset(buff, '\0', sizeof(buff));
  766.    while(1) {
  767.       cptr = strstr(rec, pcdata);
  768.       if (cptr == NULL) {
  769.          strcat(buff, rec);
  770.          for (src = dest = buff; *src != '\0';)
  771.             if (isascii(*src))
  772.                *dest++ = *src++;
  773.             else
  774.                src++;
  775.          *dest = '\0';
  776.          fprintf(cmfile, "%s\r\n", buff);
  777.          return;
  778.       }
  779.       while(rec != cptr)
  780.          *dest++ = *rec++;
  781.       strcat(buff, pcdata);
  782.       strcat(buff,"*");
  783.       dest = buff + strlen(buff);
  784.       rec += (strlen(pcdata));
  785.    }
  786. }
  787. /* ============================================================ */
  788. char *strstr(strng, ptrn)
  789. char ptrn[], strng[];
  790. {
  791.    int i, j, k;
  792.    for (i = 0; strng[i] != '\0'; i++) {
  793.       for (j = i, k=0; ptrn[k] != '\0' && strng[j] == ptrn[k]; j++, k++)
  794.          ;
  795.       if (ptrn[k] == '\0')
  796.          return(&strng[i]);
  797.    }
  798.    return(NULL);
  799. }
  800.